package com.xiaoyu.lanling.feature.register.fragment

import `in`.srain.cube.util.UTUtil
import `in`.srain.cube.util.internal.AppConsumer
import android.Manifest
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentManager
import com.amap.api.location.AMapLocation
import com.tbruyelle.rxpermissions2.RxPermissions
import com.xiaoyu.base.data.UserData
import com.xiaoyu.base.event.AppEventBus
import com.xiaoyu.base.event.SimpleEventHandler
import com.xiaoyu.base.model.User
import com.xiaoyu.base.utils.MMKVUtil
import com.xiaoyu.base.utils.RxUtils
import com.xiaoyu.base.utils.extensions.dp
import com.xiaoyu.base.utils.extensions.getViewTag
import com.xiaoyu.base.utils.extensions.setOnClickDebounceListener
import com.xiaoyu.base.utils.extensions.setViewTag
import com.xiaoyu.base.utils.upload.UploadImageOriginalType
import com.xiaoyu.base.utils.upload.UploadListener
import com.xiaoyu.base.utils.upload.UploadMediaType
import com.xiaoyu.base.utils.upload.UploadParam
import com.xiaoyu.lanling.R
import com.xiaoyu.lanling.common.Constant
import com.xiaoyu.lanling.data.AppStateData
import com.xiaoyu.lanling.event.location.AddressEvent
import com.xiaoyu.lanling.event.media.mediaselector.MediaSelectorResultEvent
import com.xiaoyu.lanling.event.register.RandomAvatarEvent
import com.xiaoyu.lanling.event.register.RegisterFirstNextButtonClickEvent
import com.xiaoyu.lanling.event.register.RegisterSecondBackButtonClickEvent
import com.xiaoyu.lanling.event.user.UserSetProfileEvent
import com.xiaoyu.lanling.feature.location.LocationData
import com.xiaoyu.lanling.feature.location.LocationHelper
import com.xiaoyu.lanling.feature.register.data.RegisterData
import com.xiaoyu.lanling.feature.user.data.UserInfoData
import com.xiaoyu.lanling.feature.user.model.UserExtra
import com.xiaoyu.lanling.media.image.ImageLoadParam
import com.xiaoyu.lanling.media.image.ImageViewUtil
import com.xiaoyu.lanling.media.selector.MediaSelector
import com.xiaoyu.lanling.media.selector.MediaSelectorFromType
import com.xiaoyu.lanling.media.selector.MediaSelectorType
import com.xiaoyu.lanling.router.Router
import com.xiaoyu.lanling.util.ImageFileCompressUtils
import com.xiaoyu.lanling.util.upload.UploadCategory
import com.xiaoyu.lanling.view.OnShowFragment
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.register_second_fragment.*
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

class RegisterSecondFragment : OnShowFragment() {

    companion object {
        private val TAG = RegisterSecondFragment::class.java.simpleName

        fun create(fragmentManager: FragmentManager): RegisterSecondFragment {
            val fragment = (fragmentManager.findFragmentByTag(TAG) as? RegisterSecondFragment)
                    ?: RegisterSecondFragment()
            return fragment
        }
    }

    private val requestTag = Any()
    private var mDisposable: Disposable? = null
    private var mPermissionDisposable: Disposable? = null
    private var mFirstNextButtonClickEvent: RegisterFirstNextButtonClickEvent? = null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.register_second_fragment, container, false)
    }

    override fun onViewCreatedSafelyAfterAppFinishInit(view: View, savedInstanceState: Bundle?) {
        super.onViewCreatedSafelyAfterAppFinishInit(view, savedInstanceState)

        initBind()
        initEvent()
    }

    override fun onStartSafelyAfterAppFinishInit(isFirstTimeStart: Boolean) {
        super.onStartSafelyAfterAppFinishInit(isFirstTimeStart)
        requestLocation()
    }

    override fun setUserVisibleHint(isVisibleToUser: Boolean) {
        super.setUserVisibleHint(isVisibleToUser)
        if (isVisibleToUser) {
            logEventForEnter()
        }
    }

    private fun logEventForEnter() {
        UTUtil.getInstance().logEvent("enter_register_avatar_page")
        UTUtil.getInstance().flushLogEvent()
    }

    private fun initBind() {
        back.setOnClickDebounceListener { RegisterSecondBackButtonClickEvent().post() }
        avatar.setOnClickDebounceListener { MediaSelector.instance.selectorForImageWithCrop(true, MediaSelectorFromType.REGISTER_AVATAR) }
        avatar_upload_tip.setOnClickDebounceListener { MediaSelector.instance.selectorForImageWithCrop(true, MediaSelectorFromType.REGISTER_AVATAR) }
        next.setOnClickDebounceListener {
            val addressEvent = it.getViewTag<AddressEvent>(Constant.GlobalViewTagDefine.VIEW_TAG_FOR_ADDRESS)
            val avatar = it.getViewTag<String>(Constant.GlobalViewTagDefine.VIEW_TAG_FOR_URL)
            next.isEnabled = false
            UserInfoData.setProfile(requestTag, mFirstNextButtonClickEvent?.name, avatar, mFirstNextButtonClickEvent?.sex, mFirstNextButtonClickEvent?.birthday, addressEvent?.province, addressEvent?.city, addressEvent?.county, mFirstNextButtonClickEvent?.inviteCode)
        }
    }

    private fun initEvent() {
        AppEventBus.bindContainerAndHandler(this, object : SimpleEventHandler() {
            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: RegisterFirstNextButtonClickEvent) {
                mFirstNextButtonClickEvent = event
                updateLayout()
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: MediaSelectorResultEvent) {
                if (event.fromType != MediaSelectorFromType.REGISTER_AVATAR) {
                    return;
                }

                if (event.isMediaEmpty || event.type != MediaSelectorType.IMAGE) {
                    return;
                }

                mDisposable = ImageFileCompressUtils.compressAsFileForAvatar(event.imagePathList[0])
                        .compose(RxUtils.ioToMainSingleScheduler())
                        .subscribe({ path ->
                            UploadParam(path, UploadCategory.AVATAR, UploadMediaType.IMAGE, "", UploadImageOriginalType.COMPRESSED).upload(object : UploadListener() {
                                override fun onSuccess(url: String) {
                                    val loadParam = ImageLoadParam.newBuilder().setUrl(url).setSizeInDP(96).setCornersRadius(8.dp).build()
                                    ImageViewUtil.loadImage(avatar, loadParam)
                                    next.setViewTag(Constant.GlobalViewTagDefine.VIEW_TAG_FOR_URL, url)
                                }
                            })
                        }, { t -> t.printStackTrace() })
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: RandomAvatarEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }
                val loadParam = ImageLoadParam.newBuilder().setEnableEmptyUrl(true).setUrl(event.avatar).setSizeInDP(96).setCornersRadius(8.dp).build()
                ImageViewUtil.loadImage(avatar, loadParam)
                next.setViewTag(Constant.GlobalViewTagDefine.VIEW_TAG_FOR_URL, event.avatar)
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: UserSetProfileEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }

                next.isEnabled = true
                if (event.isFailed) {
                    val params = Bundle()
                    params.putString("error", Log.getStackTraceString(event.failData?.exception))
                    UTUtil.getInstance().logEvent("register_error", params)
                    return
                }

                saveRegisterResult(event)

                if (event.hasSetProfile) {
                    logEventForRegisterComplete()
                    AppStateData.instance.onAppStartOrLogin()
                    activity?.let {
                        Router.instance.gotoMainActivityForNew(it, 0)
                    }
                }
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: AddressEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }
                next.setViewTag(Constant.GlobalViewTagDefine.VIEW_TAG_FOR_ADDRESS, event)
            }
        })
    }

    private fun saveRegisterResult(event: UserSetProfileEvent) {
        MMKVUtil.get(UserData.getInstance().uid).putBoolean(Constant.MMKVKey.KEY_HAS_PROFILE, event.hasSetProfile)
        UserExtra.instance.updateAndSave(event.jsonData)
        UserData.getInstance().tryUpdateSelf(event.jsonData)
    }

    private fun updateLayout() {
        mFirstNextButtonClickEvent?.let {
            RegisterData.randomAvatar(requestTag, it.sex)
            updateAvatarDemo(it.sex)
        }
    }

    private fun updateAvatarDemo(sex: String) {
        val visibility = if (sex == User.SEX_MAN) View.GONE else View.VISIBLE
        avatar_demo_disable_1.visibility = visibility
        avatar_demo_disable_2.visibility = visibility
        avatar_demo_disable_3.visibility = visibility
        avatar_demo_disable_4.visibility = visibility
    }

    private fun logEventForRegisterComplete() {
        val loginType = activity?.intent?.getStringExtra(Constant.IntentKey.KEY_LOGIN_TYPE) ?: ""

        val params = Bundle()
        params.putString("loginType", loginType)
        UTUtil.getInstance().logEvent("register_complete", params)
        UTUtil.getInstance().flushLogEvent()
    }

    private fun requestLocation() {
        activity?.let {
            mPermissionDisposable = RxPermissions(it)
                    .request(Manifest.permission.ACCESS_FINE_LOCATION)
                    .subscribe { granted ->
                        if (granted) {
                            getLocation()
                        }
                        logForRequestLocation(granted)
                    }
        }
    }

    private fun logForRequestLocation(granted: Boolean) {
        val params = Bundle()
        params.putBoolean("granted", granted)
        UTUtil.getInstance().logEvent("register_city_confirm", params)
        UTUtil.getInstance().flushLogEvent()
    }

    private fun getLocation() {
        LocationHelper().getLocation(object : AppConsumer<AMapLocation> {
            override fun accept(location: AMapLocation?) {
                if (location == null || location.longitude <= 0 || location.latitude <= 0) {
                    return
                }
                LocationData.getAddress(requestTag, location.longitude, location.latitude)
            }
        })
    }
}